#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <omnetpp.h>
#include "mpls_qos.h"
#include "MPLSPacket.h"

#include "RAR_m.h"
#include "RAA_m.h"
#include "LSP_Cost_Update_m.h"

class Ingress_Router : public cSimpleModule
{
  private:
    simtime_t timeout;
    cMessage *QOStimeoutEvent;
    int seq;
    cMessage *message;

    //LSP figure 2
	LSP *newLSP1,*newLSP2,*newLSP3,*newLSP4,*newLSP5,*newLSP6,*newLSP7,*newLSP8,*newLSP9;


  public:
    Ingress_Router();
    virtual ~Ingress_Router();

  protected:
    virtual RAR 			*generateNewMessage(int Ergress_Router_Index, int Requested_Bandwidth);
    virtual void 			sendCopyOf(cMessage *msg);
    virtual void 			initialize();
    virtual void 			handleMessage(cMessage *msg);
	virtual void            handleMessage(MPLSPacket *msg);
	virtual void            handleMessage(RAA *msg);
	virtual void            handleMessage(LSP_Cost_Update *msg);


};

Define_Module(Ingress_Router);

void Ingress_Router::handleMessage(MPLSPacket *msg) {}
void Ingress_Router::handleMessage(RAA *msg) {}
void Ingress_Router::handleMessage(LSP_Cost_Update *msg) {}


Ingress_Router::Ingress_Router()
{
    QOStimeoutEvent = message = NULL;
}

Ingress_Router::~Ingress_Router()
{
    cancelAndDelete(QOStimeoutEvent);
    delete message;
}

void Ingress_Router::initialize()
{
    // Initialize variables.
	if (strcmp("IR1", getName()) == 0)
	    {

		   newLSP1= new LSP(5,1,0,"IR1");
		   newLSP1->AddChain("CR4",4,0)->AddChain("CR8",8,0)->AddChain("CR12",12,0)->AddChain("ER",14,-1);
		   newLSP2= new LSP(5,1,0,"IR1");
		   newLSP2->AddChain("CR5",5,0)->AddChain("CR9",9,0)->AddChain("ER",14,-1);
		   newLSP3= new LSP(5,1,0,"IR1");
		   newLSP3->AddChain("CR5",4,0)->AddChain("CR8",8,0)->AddChain("CR12",12,0)->AddChain("ER",14,-1);

	    }
	if (strcmp("IR2", getName()) == 0)
	    {

		   newLSP4= new LSP(5,2,0,"IR2");
		   newLSP4->AddChain("CR5",5,0)->AddChain("CR9",9,0)->AddChain("ER",14,-1);
		   newLSP5= new LSP(5,2,0,"IR2");
		   newLSP5->AddChain("CR6",6,0)->AddChain("CR9",9,0)->AddChain("ER",14,-1);
		   newLSP6= new LSP(5,2,0,"IR2");
		   newLSP6->AddChain("CR6",6,0)->AddChain("CR10",10,0)->AddChain("ER",14,-1);


	    }
	if (strcmp("IR3", getName()) == 0)
	    {

		   newLSP7= new LSP(5,3,0,"IR3");
		   newLSP7->AddChain("CR7",7,0)->AddChain("CR11",11,0)->AddChain("CR13",13,0)->AddChain("ER",14,-1);
		   newLSP8= new LSP(5,3,0,"IR3");
		   newLSP8->AddChain("CR6",6,0)->AddChain("CR10",10,0)->AddChain("ER",14,-1);
		   newLSP9= new LSP(5,3,0,"IR3");
		   newLSP9->AddChain("CR7",7,0)->AddChain("CR10",10,0)->AddChain("CR13",13,0)->AddChain("ER",14,-1);

	    }
    seq = 0;

    //TODO: make this randomally distributed
    timeout = 1.0;

    QOStimeoutEvent = new cMessage("QOStimeoutEvent");

    EV << "Sending initial QOS message\n";

   // message = generateNewMessage();

    //message = generateNewMessage(14,1);
    sendCopyOf(message);

    scheduleAt(simTime()+timeout, QOStimeoutEvent);
}

void Ingress_Router::handleMessage(cMessage *msg)
{
    if (msg==QOStimeoutEvent)
    {

    	EV << "QOS Request\n";

    	sendCopyOf(message);

        scheduleAt(simTime()+timeout, QOStimeoutEvent);
    }
    else // message arrived
    {
        // Acknowledgement received!
        EV << "Received: " << msg->getName() << "\n";
        delete msg;

        cancelEvent(QOStimeoutEvent);
        delete message;

        // Ready to send another one.
        //message = generateNewMessage();
        sendCopyOf(message);
        scheduleAt(simTime()+timeout, QOStimeoutEvent);
    }
}


void Ingress_Router::sendCopyOf(cMessage *msg)
{
    // Duplicate message and send the copy.
   // cMessage *copy = (cMessage *) msg->dup();
    MPLSPacket *newMsg = new MPLSPacket("One");

   //send(copy, "gate");
    // Same routing as before: random gate.
    //int n = gateSize("gate");
    //int k = intuniform(0,n-1);

    send(newMsg, "gate$o", 0);
    //send(copy, "gate$o", 0);
}

RAR *Ingress_Router::generateNewMessage(int Ergress_Router_Index, int Requested_Bandwidth)
{
	RAR *msg = new RAR();

	msg->setErgress_Router_Index(Ergress_Router_Index);
	msg->setRequested_Bandwidth(Requested_Bandwidth);

	return msg;
}
